home *** CD-ROM | disk | FTP | other *** search
/ C/C++ Users Group Library 1996 July / C-C++ Users Group Library July 1996.iso / listings / v_13_08 / phillip2 / skeleton.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-05-14  |  37.8 KB  |  1,433 lines

  1.  
  2.        /**********************************************
  3.        *
  4.        *       file d:\cips\skeleton.c
  5.        *
  6.        *       Functions: This file contains
  7.        *          thinning
  8.        *          can_thin
  9.        *          dilate_not_join
  10.        *          can_dilate
  11.        *          little_label_and_check
  12.        *          special_closing
  13.        *          special_opening
  14.        *          edm
  15.        *          distanc_8
  16.        *          mat
  17.        *          mat_d
  18.        *
  19.        *       Purpose:
  20.        *          These functions thin objects in
  21.        *          an image, dilate objects, and
  22.        *          perform opening and closing
  23.        *          without removing or joining
  24.        *          objects.
  25.        *
  26.        *       External Calls:
  27.        *          wtiff.c - round_off_image_size
  28.        *                    create_file_if_needed
  29.        *                    write_array_into_tiff_image
  30.        *          tiff.c - read_tiff_header
  31.        *          rtiff.c - read_tiff_image
  32.        *          numcvrt.c - get_integer
  33.        *
  34.        *
  35.        *       Modifications:
  36.        *          7 March 1993 - created
  37.        *
  38.        ************************************************/
  39.  
  40. #include "cips.h"
  41.  
  42.  
  43.  
  44.  
  45.  
  46.      /*******************************************
  47.      *
  48.      *   thinning(...
  49.      *
  50.      *   Use a variation of the grass fire
  51.      *   wave front approach.
  52.      *
  53.      *   Raster scan the image left to right
  54.      *   and examine and thin the left edge pixels
  55.      *   (a 0 to value transition).  Process them
  56.      *   normally and "save" the result.  Next,
  57.      *   raster scan the image right to left and
  58.      *   save.  Raster scan top to bottom and save.
  59.      *   Raster scan bottom to top and save.
  60.      *
  61.      *   That is one complete pass.
  62.      *
  63.      *   Keep track of pixels thinned for a
  64.      *   pass and quit when you make a complete
  65.      *   pass without thinning any pixels.
  66.      *
  67.      *******************************************/
  68.  
  69.  
  70. thinning(in_name, out_name, the_image, out_image,
  71.          il, ie, ll, le, value, threshold, once_only)
  72.    char   in_name[], out_name[];
  73.    int    il, ie, ll, le, once_only;
  74.    short  the_image[ROWS][COLS],
  75.           out_image[ROWS][COLS],
  76.           threshold, value;
  77. {
  78.    int    a, b, big_count, count, i, j, k,
  79.           not_finished;
  80.  
  81.    create_file_if_needed(in_name, out_name, out_image);
  82.  
  83.    read_tiff_image(in_name, the_image, il, ie, ll, le);
  84.  
  85.  
  86.    for(i=0; i<ROWS; i++)
  87.       for(j=0; j<COLS; j++)
  88.          out_image[i][j] = the_image[i][j];
  89.  
  90.    not_finished = 1;
  91.    while(not_finished){
  92.  
  93.       if(once_only == 1)
  94.         not_finished = 0;
  95.       big_count = 0;
  96.  
  97.          /***************************
  98.          *
  99.          *   Scan left to right
  100.          *   Look for 0-value transition
  101.          *
  102.          ****************************/
  103.  
  104.       printf("\n");
  105.       for(i=1; i<ROWS-1; i++){
  106.          if( (i%10) == 0) printf("%3d", i);
  107.          for(j=1; j<COLS-1; j++){
  108.             if(the_image[i][j-1] == 0   &&
  109.                the_image[i][j]   == value){
  110.                count = 0;
  111.                for(a=-1; a<=1; a++){
  112.                    for(b=-1; b<=1; b++){
  113.                          if(the_image[i+a][j+b] == 0)
  114.                             count++;
  115.                    }  /*  ends loop over b */
  116.                }  /* ends loop over a */
  117.                if(count > threshold){
  118.                   if(can_thin(the_image, i, j, value)){
  119.                      out_image[i][j] = 0;
  120.                      big_count++;
  121.                   }  /* ends if can_thin */
  122.                }  /* ends if count > threshold */
  123.             }  /* ends if the_image == value */
  124.          }  /* ends loop over j */
  125.       }  /* ends loop over i */
  126.  
  127.          /**************************************
  128.          *
  129.          *   Copy the output back to the input.
  130.          *
  131.          **************************************/
  132.  
  133.       for(i=0; i<ROWS; i++)
  134.          for(j=0; j<COLS; j++)
  135.             the_image[i][j] = out_image[i][j];
  136.  
  137.  
  138.          /***************************
  139.          *
  140.          *   Scan right to left
  141.          *   Do this by scanning left
  142.          *   to right and look for
  143.          *   value-0 transition.
  144.          *
  145.          ****************************/
  146.  
  147.       printf("\n");
  148.       for(i=1; i<ROWS-1; i++){
  149.          if( (i%10) == 0) printf("%3d", i);
  150.          for(j=1; j<COLS-1; j++){
  151.             if(the_image[i][j+1] == 0   &&
  152.                the_image[i][j]   == value){
  153.                count = 0;
  154.                for(a=-1; a<=1; a++){
  155.                    for(b=-1; b<=1; b++){
  156.                          if(the_image[i+a][j+b] == 0)
  157.                             count++;
  158.                    }  /*  ends loop over b */
  159.                }  /* ends loop over a */
  160.                if(count > threshold){
  161.                   if(can_thin(the_image, i, j, value)){
  162.                      out_image[i][j] = 0;
  163.                      big_count++;
  164.                   }  /* ends if can_thin */
  165.                }  /* ends if count > threshold */
  166.             }  /* ends if the_image == value */
  167.          }  /* ends loop over j */
  168.       }  /* ends loop over i */
  169.  
  170.          /**************************************
  171.          *
  172.          *   Copy the output back to the input.
  173.          *
  174.          **************************************/
  175.  
  176.       for(i=0; i<ROWS; i++)
  177.          for(j=0; j<COLS; j++)
  178.             the_image[i][j] = out_image[i][j];
  179.  
  180.  
  181.          /***************************
  182.          *
  183.          *   Scan top to bottom
  184.          *   Look for 0-value transition
  185.          *
  186.          ****************************/
  187.  
  188.       printf("\n");
  189.       for(j=1; j<COLS-1; j++){
  190.          if( (j%10) == 0) printf("%3d", j);
  191.          for(i=1; i<ROWS-1; i++){
  192.             if(the_image[i-1][j] == 0   &&
  193.                the_image[i][j]   == value){
  194.                count = 0;
  195.                for(a=-1; a<=1; a++){
  196.                    for(b=-1; b<=1; b++){
  197.                          if(the_image[i+a][j+b] == 0)
  198.                             count++;
  199.                    }  /*  ends loop over b */
  200.                }  /* ends loop over a */
  201.                if(count > threshold){
  202.                   if(can_thin(the_image, i, j, value)){
  203.                      out_image[i][j] = 0;
  204.                      big_count++;
  205.                   }  /* ends if can_thin */
  206.                }  /* ends if count > threshold */
  207.             }  /* ends if the_image == value */
  208.          }  /* ends loop over i */
  209.       }  /* ends loop over j */
  210.  
  211.          /**************************************
  212.          *
  213.          *   Copy the output back to the input.
  214.          *
  215.          **************************************/
  216.  
  217.       for(i=0; i<ROWS; i++)
  218.          for(j=0; j<COLS; j++)
  219.             the_image[i][j] = out_image[i][j];
  220.  
  221.  
  222.  
  223.          /***************************
  224.          *
  225.          *   Scan bottom to top
  226.          *   Do this by scanning top
  227.          *   to bottom and look for
  228.          *   value-0 transition.
  229.          *
  230.          ****************************/
  231.  
  232.       printf("\n");
  233.       for(j=1; j<COLS-1; j++){
  234.          if( (j%10) == 0) printf("%3d", j);
  235.          for(i=1; i<ROWS-1; i++){
  236.             if(the_image[i+1][j] == 0   &&
  237.                the_image[i][j]   == value){
  238.                count = 0;
  239.                for(a=-1; a<=1; a++){
  240.                    for(b=-1; b<=1; b++){
  241.                          if(the_image[i+a][j+b] == 0)
  242.                             count++;
  243.                    }  /*  ends loop over b */
  244.                }  /* ends loop over a */
  245.                if(count > threshold){
  246.                   if(can_thin(the_image, i, j, value)){
  247.                      out_image[i][j] = 0;
  248.                      big_count++;
  249.                   }  /* ends if can_thin */
  250.                }  /* ends if count > threshold */
  251.             }  /* ends if the_image == value */
  252.          }  /* ends loop over i */
  253.       }  /* ends loop over j */
  254.  
  255.          /**************************************
  256.          *
  257.          *   Copy the output back to the input.
  258.          *
  259.          **************************************/
  260.  
  261.       for(i=0; i<ROWS; i++)
  262.          for(j=0; j<COLS; j++)
  263.             the_image[i][j] = out_image[i][j];
  264.  
  265.          /**************************************
  266.          *
  267.          *   Now look at the result of this big
  268.          *   pass through the image.
  269.          *
  270.          ***************************************/
  271.  
  272.       printf("\n\nThinned %d pixels", big_count);
  273.       if(big_count == 0)
  274.          not_finished = 0;
  275.       else{
  276.          for(i=0; i<ROWS; i++)
  277.             for(j=0; j<COLS; j++)
  278.                the_image[i][j] = out_image[i][j];
  279.       }  /* ends else */
  280.  
  281.    }  /* ends while not_finished */
  282.  
  283.    fix_edges(out_image, 3);
  284.    write_array_into_tiff_image(out_name, out_image,
  285.                                il, ie, ll, le);
  286. }  /* ends thinning */
  287.  
  288.  
  289.  
  290.  
  291.  
  292.      /*******************************************
  293.      *
  294.      *   can_thin(...
  295.      *
  296.      *   Look at the neighbors of the center pixel.
  297.      *   If a neighbor == value, then it must
  298.      *   have a neighbor == value other than the
  299.      *   center pixel.
  300.      *
  301.      *   Procedure:
  302.      *   . Copy the 3x3 area surrounding pixel
  303.      *     i,j to a temp array.
  304.      *   . Set the center pixel to zero.
  305.      *   . Look at each non-zero pixel in temp.
  306.      *      . If you cannot find a non-zero
  307.      *        neighbor.
  308.      *      . Then you cannot thin.
  309.      *
  310.      *******************************************/
  311.  
  312. can_thin(the_image, i, j, value)
  313.    int   i, j;
  314.    short the_image[ROWS][COLS], value;
  315. {
  316.    int   a, b, c, d, count,
  317.          no_neighbor, one=1, zero=0;
  318.    short temp[3][3];
  319.  
  320.        /**************************************
  321.        *
  322.        *   Copy the center pixel and its
  323.        *   neighbors to the temp array.
  324.        *
  325.        ***************************************/
  326.  
  327.    for(a=-1; a<2; a++)
  328.       for(b=-1; b<2; b++)
  329.          temp[a+1][b+1] = the_image[i+a][b+j];
  330.  
  331.        /**************************************
  332.        *
  333.        *   Set the center of temp to 0.
  334.        *
  335.        ***************************************/
  336.  
  337.    temp[1][1] = 0;
  338.  
  339.        /**************************************
  340.        *
  341.        *   Check the non-zero pixels in temp.
  342.        *
  343.        ***************************************/
  344.  
  345.    for(a=0; a<3; a++){
  346.       for(b=0; b<3; b++){
  347.          if(temp[a][b] == value){
  348.             temp[a][b] = 0;
  349.  
  350.                 /**************************************
  351.                 *
  352.                 *   Check the neighbors of this pixel
  353.                 *   If there is a single non-zero
  354.                 *   neighbor, set no_neighbor = 0.
  355.                 *
  356.                 ***************************************/
  357.  
  358.             no_neighbor = 1;
  359.             for(c=-1; c<2; c++){
  360.                for(d=-1; d<2; d++){
  361.                   if( ((a+c) >= 0)   &&
  362.                       ((a+c) <= 2)   &&
  363.                       ((b+d) >= 0)   &&
  364.                       ((b+d) <= 2)){
  365.                      if(temp[a+c][b+d] == value){
  366.                         no_neighbor = 0;
  367.                      }  /* ends if temp == value */
  368.                   }  /* ends if part of temp array */
  369.                }  /* ends loop over d */
  370.             }  /* ends loop over c */
  371.             temp[a][b] = value;
  372.  
  373.                 /**************************************
  374.                 *
  375.                 *   If the non-zero pixel did not
  376.                 *   have any non-zero neighbors,
  377.                 *   no_neighbor still equals 1,
  378.                 *   and we cannot thin, so return
  379.                 *   zero.
  380.                 *
  381.                 ***************************************/
  382.  
  383.             if(no_neighbor){
  384.                return(zero);
  385.             }
  386.          }  /* ends if temp[a][b] == value */
  387.       }  /* ends loop over b */
  388.    }  /* ends loop over a */
  389.  
  390.        /**************************************
  391.        *
  392.        *   First, ensure the object is more
  393.        *   than two wide.  If it is two wide,
  394.        *   you will thin out the entire object.
  395.        *   Check in all eight directions.
  396.        *   If the distance to a zero is 0 or
  397.        *   >= 2, then ok you can thin so go
  398.        *   on to the remainder of this routine.
  399.        *   If not, you cannot thin so return
  400.        *   zero.
  401.        *
  402.        ***************************************/
  403.  
  404.    return(one);
  405.  
  406. }  /* ends can_thin */
  407.  
  408.  
  409.  
  410.  
  411.  
  412.      /*******************************************
  413.      *
  414.      *   dilate_not_join(...
  415.      *
  416.      *   Use a variation of the grass fire
  417.      *   wave front approach.
  418.      *
  419.      *   Raster scan the image left to right
  420.      *   and examine and dilate the left edge pixels
  421.      *   (a value to 0 transition).  Process them
  422.      *   normally and "save" the result.  Next,
  423.      *   raster scan the image right to left and
  424.      *   save.  Raster scan top to bottom and save.
  425.      *   Raster scan bottom to top and save.
  426.      *
  427.      *   That is one complete pass.
  428.      *
  429.      *******************************************/
  430.  
  431. dilate_not_join(in_name, out_name, the_image, out_image,
  432.                 il, ie, ll, le, value, threshold)
  433.    char   in_name[], out_name[];
  434.    int    il, ie, ll, le;
  435.    short  the_image[ROWS][COLS],
  436.           out_image[ROWS][COLS],
  437.           threshold, value;
  438. {
  439.    int    a, b, count, i, j, k;
  440.  
  441.    create_file_if_needed(in_name, out_name, out_image);
  442.  
  443.    read_tiff_image(in_name, the_image, il, ie, ll, le);
  444.  
  445.  
  446.    for(i=0; i<ROWS; i++)
  447.       for(j=0; j<COLS; j++)
  448.          out_image[i][j] = the_image[i][j];
  449.  
  450.          /***************************
  451.          *
  452.          *   Scan left to right
  453.          *   Look for value-0 transition
  454.          *
  455.          ****************************/
  456.  
  457.       printf("\n");
  458.       for(i=1; i<ROWS-1; i++){
  459.          if( (i%10) == 0) printf("%3d", i);
  460.          for(j=1; j<COLS-1; j++){
  461.             if(the_image[i][j-1] == value  &&
  462.                the_image[i][j]   == 0){
  463.                count = 0;
  464.                for(a=-1; a<=1; a++){
  465.                    for(b=-1; b<=1; b++){
  466.                          if(the_image[i+a][j+b]==value)
  467.                             count++;
  468.                    }  /*  ends loop over b */
  469.                }  /* ends loop over a */
  470.                if(count > threshold){
  471.                   if(can_dilate(the_image,i,j,value)){
  472.                      out_image[i][j] = value;
  473.                   }  /* ends if can_dilate */
  474.                }  /* ends if count > threshold */
  475.             }  /* ends if the_image == value */
  476.          }  /* ends loop over j */
  477.       }  /* ends loop over i */
  478.  
  479.          /**************************************
  480.          *
  481.          *   Copy the output back to the input.
  482.          *
  483.          **************************************/
  484.  
  485.       for(i=0; i<ROWS; i++)
  486.          for(j=0; j<COLS; j++)
  487.             the_image[i][j] = out_image[i][j];
  488.  
  489.  
  490.          /***************************
  491.          *
  492.          *   Scan right to left
  493.          *   Do this by scanning left
  494.          *   to right and look for
  495.          *   0-value transition.
  496.          *
  497.          ****************************/
  498.  
  499.       printf("\n");
  500.       for(i=1; i<ROWS-1; i++){
  501.          if( (i%10) == 0) printf("%3d", i);
  502.          for(j=1; j<COLS-1; j++){
  503.             if(the_image[i][j+1] == value   &&
  504.                the_image[i][j]   == 0){
  505.                count = 0;
  506.                for(a=-1; a<=1; a++){
  507.                    for(b=-1; b<=1; b++){
  508.                          if(the_image[i+a][j+b]==value)
  509.                             count++;
  510.                    }  /*  ends loop over b */
  511.                }  /* ends loop over a */
  512.                if(count > threshold){
  513.                   if(can_dilate(the_image,i,j,value)){
  514.                      out_image[i][j] = value;
  515.                   }  /* ends if can_dilate */
  516.                }  /* ends if count > threshold */
  517.             }  /* ends if the_image == value */
  518.          }  /* ends loop over j */
  519.       }  /* ends loop over i */
  520.  
  521.          /**************************************
  522.          *
  523.          *   Copy the output back to the input.
  524.          *
  525.          **************************************/
  526.  
  527.       for(i=0; i<ROWS; i++)
  528.          for(j=0; j<COLS; j++)
  529.             the_image[i][j] = out_image[i][j];
  530.  
  531.  
  532.          /***************************
  533.          *
  534.          *   Scan top to bottom
  535.          *   Look for value-0 transition
  536.          *
  537.          ****************************/
  538.  
  539.       printf("\n");
  540.       for(j=1; j<COLS-1; j++){
  541.          if( (j%10) == 0) printf("%3d", j);
  542.          for(i=1; i<ROWS-1; i++){
  543.             if(the_image[i-1][j] == value   &&
  544.                the_image[i][j]   == 0){
  545.                count = 0;
  546.                for(a=-1; a<=1; a++){
  547.                    for(b=-1; b<=1; b++){
  548.                          if(the_image[i+a][j+b]==value)
  549.                             count++;
  550.                    }  /*  ends loop over b */
  551.                }  /* ends loop over a */
  552.                if(count > threshold){
  553.                   if(can_dilate(the_image,i,j,value)){
  554.                      out_image[i][j] = value;
  555.                   }  /* ends if can_dilate */
  556.                }  /* ends if count > threshold */
  557.             }  /* ends if the_image == value */
  558.          }  /* ends loop over i */
  559.       }  /* ends loop over j */
  560.  
  561.          /**************************************
  562.          *
  563.          *   Copy the output back to the input.
  564.          *
  565.          **************************************/
  566.  
  567.       for(i=0; i<ROWS; i++)
  568.          for(j=0; j<COLS; j++)
  569.             the_image[i][j] = out_image[i][j];
  570.  
  571.  
  572.  
  573.          /***************************
  574.          *
  575.          *   Scan bottom to top
  576.          *   Do this by scanning top
  577.          *   to bottom and look for
  578.          *   0-value transition.
  579.          *
  580.          ****************************/
  581.  
  582.       printf("\n");
  583.       for(j=1; j<COLS-1; j++){
  584.          if( (j%10) == 0) printf("%3d", j);
  585.          for(i=1; i<ROWS-1; i++){
  586.             if(the_image[i+1][j] == value   &&
  587.                the_image[i][j]   == 0){
  588.                count = 0;
  589.                for(a=-1; a<=1; a++){
  590.                    for(b=-1; b<=1; b++){
  591.                          if(the_image[i+a][j+b]==value)
  592.                             count++;
  593.                    }  /*  ends loop over b */
  594.                }  /* ends loop over a */
  595.                if(count > threshold){
  596.                   if(can_dilate(the_image,i,j,value)){
  597.                      out_image[i][j] = value;
  598.                   }  /* ends if can_dilate */
  599.                }  /* ends if count > threshold */
  600.             }  /* ends if the_image == value */
  601.          }  /* ends loop over i */
  602.       }  /* ends loop over j */
  603.  
  604.          /**************************************
  605.          *
  606.          *   Copy the output back to the input.
  607.          *
  608.          **************************************/
  609.  
  610.       for(i=0; i<ROWS; i++)
  611.          for(j=0; j<COLS; j++)
  612.             the_image[i][j] = out_image[i][j];
  613.  
  614.  
  615.    fix_edges(out_image, 3);
  616.  
  617.    write_array_into_tiff_image(out_name, out_image,
  618.                                il, ie, ll, le);
  619.  
  620. }  /* ends dilate_not_join */
  621.  
  622.  
  623.  
  624.  
  625.  
  626.      /*******************************************
  627.      *
  628.      *   can_dilate(...
  629.      *
  630.      *   This function decides if you can dilate
  631.      *   (set to value) a pixel without joining
  632.      *   two separate objects in a 3x3 area.
  633.      *
  634.      *   First, you grow regions inside the 3x3
  635.      *   area.  Next, check if the center pixel
  636.      *   has neighbors with differing values.
  637.      *   If it does, you cannot dilate it because
  638.      *   that would join two separate objects.
  639.      *
  640.      *******************************************/
  641.  
  642. can_dilate(the_image, i, j, value)
  643.    int   i, j;
  644.    short the_image[ROWS][COLS], value;
  645. {
  646.    int   a, b, c, d, count, found=0,
  647.          no_neighbor,
  648.          stack_pointer=-1,
  649.          stack_empty=1,
  650.          stack[12][2],
  651.          pop_a, pop_b,
  652.          one=1,
  653.          zero=0;
  654.    short first_value, label = 2, temp[3][3];
  655.  
  656.        /**************************************
  657.        *
  658.        *   Copy the center pixel and its
  659.        *   neighbors to the temp array.
  660.        *
  661.        ***************************************/
  662.  
  663.    for(a=-1; a<2; a++)
  664.       for(b=-1; b<2; b++)
  665.          temp[a+1][b+1] = the_image[i+a][b+j];
  666.  
  667.        /**************************************
  668.        *
  669.        *   Grow objects inside the temp array.
  670.        *
  671.        ***************************************/
  672.  
  673.    for(a=0; a<3; a++){
  674.       for(b=0; b<3; b++){
  675.          stack_empty   = 1;
  676.          stack_pointer = -1;
  677.          if(temp[a][b] == value){
  678.             little_label_and_check(temp, stack, label,
  679.                                    &stack_empty,
  680.                                    &stack_pointer,
  681.                                    a, b, value);
  682.             found = 1;
  683.          }  /* ends if temp == value */
  684.  
  685.          while(stack_empty == 0){
  686.             pop_a = stack[stack_pointer][0]; /* POP */
  687.             pop_b = stack[stack_pointer][1]; /* POP */
  688.             --stack_pointer;
  689.             if(stack_pointer <= 0){
  690.                stack_pointer = 0;
  691.                stack_empty   = 1;
  692.             }  /* ends if stack_pointer */
  693.             little_label_and_check(temp, stack, label,
  694.                                    &stack_empty,
  695.                                    &stack_pointer,
  696.                                    pop_a, pop_b, value);
  697.          }  /* ends while stack_empty == 0 */
  698.  
  699.          if(found){
  700.             found = 0;
  701.             label++;
  702.          }  /* ends if object_found */
  703.       }  /* ends loop over b */
  704.    }  /* ends loop over a */
  705.  
  706.        /**************************************
  707.        *
  708.        *   Look at the center pixel.  If it
  709.        *   has two non-zero neigbors whose
  710.        *   pixels are not the same, then
  711.        *   you cannot dilate.
  712.        *
  713.        ***************************************/
  714.  
  715.    first_value = -1;
  716.    for(a=0; a<3; a++){
  717.       for(b=0; b<3; b++){
  718.          if(temp[a][b]  != 0 &&
  719.             first_value == -1){
  720.             first_value = temp[a][b];
  721.          }
  722.          if(temp[a][b]  != 0  &&
  723.             first_value != -1){
  724.             if(temp[a][b] != first_value){
  725.                return(zero);
  726.             }
  727.          }
  728.       }  /* ends loop over b */
  729.    }  /* ends loop over a */
  730.  
  731.    return(one);
  732.  
  733. }  /* ends can_dilate */
  734.  
  735.  
  736.  
  737.  
  738.  
  739.      /*******************************************
  740.      *
  741.      *   little_label_and_check(...
  742.      *
  743.      *   This function labels the objects in
  744.      *   in a 3x3 area.
  745.      *
  746.      *******************************************/
  747.  
  748. little_label_and_check(temp, stack, label, stack_empty,
  749.                        stack_pointer, a, b, value)
  750.    int   a, b, stack[12][2], 
  751.          *stack_empty, *stack_pointer;
  752.    short temp[3][3], label, value;
  753. {
  754.    int c, d;
  755.  
  756.    temp[a][b] = label;
  757.    for(c=a-1; c<=a+1; c++){
  758.       for(d=b-1; d<=b+1; d++){
  759.          if(c >= 0      &&
  760.             c <= 2      &&
  761.             d >= 0      &&
  762.             d <= 2)
  763.             if(temp[c][d] == value){  /* PUSH */
  764.                *stack_pointer = *stack_pointer + 1;
  765.                stack[*stack_pointer][0] = c;
  766.                stack[*stack_pointer][1] = d;
  767.                *stack_empty = 0;
  768.             }  /* ends if temp == value */
  769.       }  /* ends loop over d */
  770.    }  /* ends loop over c */
  771.  
  772. }  /* ends little_label_and_check */
  773.  
  774.  
  775.  
  776.  
  777.  
  778.      /*******************************************
  779.      *
  780.      *   special_closing(...
  781.      *
  782.      *   Closing is dilation followed by erosion.
  783.      *   This routine will use the dilate_not_join
  784.      *   dilation routine.  This will not allow
  785.      *   two separate objects to join.
  786.      *
  787.      *   The number parameter specifies how
  788.      *   dilations to perform before doing one
  789.      *   erosion.
  790.      *
  791.      *******************************************/
  792.  
  793. special_closing(in_name, out_name, the_image,
  794.                 out_image, il, ie, ll, le,
  795.                 value, threshold, number)
  796.    char   in_name[], out_name[];
  797.    int    il, ie, ll, le, number;
  798.    short  the_image[ROWS][COLS],
  799.           out_image[ROWS][COLS],
  800.           threshold, value;
  801. {
  802.    int    a, b, count, i, j, k;
  803.  
  804.    create_file_if_needed(in_name, out_name, out_image);
  805.  
  806.    read_tiff_image(in_name, the_image, il, ie, ll, le);
  807.  
  808.    dilate_not_join(in_name, out_name, the_image,
  809.                    out_image, il, ie, ll, le,
  810.                    value, threshold);
  811.  
  812.    if(number > 1){
  813.       count = 1;
  814.       while(count < number){
  815.          count++;
  816.          dilate_not_join(out_name, out_name, the_image,
  817.                          out_image, il, ie, ll, le,
  818.                          value, threshold);
  819.       }  /* ends while */
  820.    }  /* ends if number > 1 */
  821.  
  822.    erosion(out_name, out_name, the_image,
  823.            out_image, il, ie, ll, le,
  824.            value, threshold);
  825.  
  826.    write_array_into_tiff_image(out_name, out_image,
  827.                                il, ie, ll, le);
  828.  
  829. }  /* ends special_closing */
  830.  
  831.  
  832.  
  833.  
  834.  
  835.      /*******************************************
  836.      *
  837.      *   special_opening(...
  838.      *
  839.      *   Opening is erosion followed by dilation.
  840.      *   This routine will use the thinning
  841.      *   erosion routine.  This will not allow
  842.      *   an object to erode to nothing.
  843.      *
  844.      *   The number parameter specifies how
  845.      *   erosions to perform before doing one
  846.      *   dilation.
  847.      *
  848.      *******************************************/
  849.  
  850. special_opening(in_name, out_name, the_image,
  851.                 out_image, il, ie, ll, le,
  852.                 value, threshold, number)
  853.    char   in_name[], out_name[];
  854.    int    il, ie, ll, le, number;
  855.    short  the_image[ROWS][COLS],
  856.           out_image[ROWS][COLS],
  857.           threshold, value;
  858. {
  859.    int    a, b, count, i, j, k;
  860.  
  861.    create_file_if_needed(in_name, out_name, out_image);
  862.  
  863.    read_tiff_image(in_name, the_image, il, ie, ll, le);
  864.  
  865.    thinning(in_name, out_name, the_image,
  866.             out_image, il, ie, ll, le,
  867.             value, threshold, 1);
  868.  
  869.    if(number > 1){
  870.       count = 1;
  871.       while(count < number){
  872.          count++;
  873.          thinning(out_name, out_name, the_image,
  874.                   out_image, il, ie, ll, le,
  875.                   value, threshold, 1);
  876.       }  /* ends while */
  877.    }  /* ends if number > 1 */
  878.  
  879.    dilation(out_name, out_name, the_image,
  880.             out_image, il, ie, ll, le,
  881.             value, threshold);
  882.  
  883.    write_array_into_tiff_image(out_name, out_image,
  884.                                il, ie, ll, le);
  885.  
  886. }  /* ends special_opening */
  887.  
  888.  
  889.  
  890.  
  891.  
  892.      /*******************************************
  893.      *
  894.      *   edm(..
  895.      *
  896.      *   This function calculates the Euclidean
  897.      *   distance measure for objects in an image.
  898.      *   It calculates the distance from any
  899.      *   pixel=value to the nearest zero pixel
  900.      *
  901.      *******************************************/
  902.  
  903.  
  904. edm(in_name, out_name, the_image, out_image,
  905.           il, ie, ll, le, value)
  906.    char   in_name[], out_name[];
  907.    int    il, ie, ll, le;
  908.    short  the_image[ROWS][COLS],
  909.           out_image[ROWS][COLS],
  910.           value;
  911. {
  912.    int    a, b, count, i, j, k;
  913.  
  914.    create_file_if_needed(in_name, out_name, out_image);
  915.  
  916.    read_tiff_image(in_name, the_image, il, ie, ll, le);
  917.  
  918.    for(i=0; i<ROWS; i++)
  919.       for(j=0; j<COLS; j++)
  920.          out_image[i][j] = 0;
  921.  
  922.       /***************************
  923.       *
  924.       *   Loop over image array
  925.       *
  926.       ****************************/
  927.  
  928.    printf("\n");
  929.  
  930.    for(i=0; i<ROWS; i++){
  931.       if( (i%10) == 0) printf("%3d", i);
  932.       for(j=0; j<COLS; j++){
  933.          if(the_image[i][j] == value)
  934.             out_image[i][j] = distance_8(the_image, 
  935.                                          i, j, value);
  936.       }  /* ends loop over j */
  937.    }  /* ends loop over i */
  938.  
  939.    write_array_into_tiff_image(out_name, out_image,
  940.                                il, ie, ll, le);
  941.  
  942. }  /* ends edm */
  943.  
  944.  
  945.  
  946.      /*******************************************
  947.      *
  948.      *   distance_8(..
  949.      *
  950.      *   This function finds the distance from
  951.      *   a pixel to the nearest zero pixel.
  952.      *   It search in all eight directions.
  953.      *
  954.      *******************************************/
  955.  
  956. distance_8(the_image, a, b, value)
  957.    int   a, b;
  958.    short the_image[ROWS][COLS], value;
  959. {
  960.    int i, j, measuring;
  961.    short dist1  = 0,
  962.          dist2  = 0,
  963.          dist3  = 0,
  964.          dist4  = 0,
  965.          dist5  = 0,
  966.          dist6  = 0,
  967.          dist7  = 0,
  968.          dist8  = 0,
  969.          result = 0;
  970.  
  971.       /* straight up */
  972.    measuring = 1;
  973.    i = a;
  974.    j = b;
  975.    while(measuring){
  976.       i--;
  977.       if(i >= 0){
  978.          if(the_image[i][j] == value)
  979.             dist1++;
  980.          else
  981.             measuring = 0;
  982.       }
  983.       else
  984.          measuring = 0;
  985.    }  /* ends while measuring */
  986.    result = dist1;
  987.  
  988.       /* straight down */
  989.    measuring = 1;
  990.    i = a;
  991.    j = b;
  992.    while(measuring){
  993.       i++;
  994.       if(i <= ROWS-1){
  995.          if(the_image[i][j] == value)
  996.             dist2++;
  997.          else
  998.             measuring = 0;
  999.       }
  1000.       else
  1001.          measuring = 0;
  1002.    }  /* ends while measuring */
  1003.    if(dist2 <= result)
  1004.       result = dist2;
  1005.  
  1006.       /* straight left */
  1007.    measuring = 1;
  1008.    i = a;
  1009.    j = b;
  1010.    while(measuring){
  1011.       j--;
  1012.       if(j >= 0){
  1013.          if(the_image[i][j] == value)
  1014.             dist3++;
  1015.          else
  1016.             measuring = 0;
  1017.       }
  1018.       else
  1019.          measuring = 0;
  1020.    }  /* ends while measuring */
  1021.    if(dist3 <= result)
  1022.       result = dist3;
  1023.  
  1024.       /* straight right */
  1025.    measuring = 1;
  1026.    i = a;
  1027.    j = b;
  1028.    while(measuring){
  1029.       j++;
  1030.       if(j <= COLS-1){
  1031.          if(the_image[i][j] == value)
  1032.             dist4++;
  1033.          else
  1034.             measuring = 0;
  1035.       }
  1036.       else
  1037.          measuring = 0;
  1038.    }  /* ends while measuring */
  1039.    if(dist4 <= result)
  1040.       result = dist4;
  1041.  
  1042.       /* left and up */
  1043.    measuring = 1;
  1044.    i = a;
  1045.    j = b;
  1046.    while(measuring){
  1047.       j--;
  1048.       i--;
  1049.       if(j >= 0 && i>=0){
  1050.          if(the_image[i][j] == value)
  1051.             dist5++;
  1052.          else
  1053.             measuring = 0;
  1054.       }
  1055.       else
  1056.          measuring = 0;
  1057.    }  /* ends while measuring */
  1058.    dist5 = (dist5*14)/10;
  1059.    if(dist5 <= result)
  1060.       result = dist5;
  1061.  
  1062.       /* right and up */
  1063.    measuring = 1;
  1064.    i = a;
  1065.    j = b;
  1066.    while(measuring){
  1067.       j++;
  1068.       i--;
  1069.       if(j <=COLS-1 && i>=0){
  1070.          if(the_image[i][j] == value)
  1071.             dist6++;
  1072.          else
  1073.             measuring = 0;
  1074.       }
  1075.       else
  1076.          measuring = 0;
  1077.    }  /* ends while measuring */
  1078.    dist6 = (dist6*14)/10;
  1079.    if(dist6 <= result)
  1080.       result = dist6;
  1081.  
  1082.       /* right and down */
  1083.    measuring = 1;
  1084.    i = a;
  1085.    j = b;
  1086.    while(measuring){
  1087.       j++;
  1088.       i++;
  1089.       if(j <=COLS-1 && i<=ROWS-1){
  1090.          if(the_image[i][j] == value)
  1091.             dist7++;
  1092.          else
  1093.             measuring = 0;
  1094.       }
  1095.       else
  1096.          measuring = 0;
  1097.    }  /* ends while measuring */
  1098.    dist7 = (dist7*14)/10;
  1099.    if(dist7 <= result)
  1100.       result = dist7;
  1101.  
  1102.       /* left and down */
  1103.    measuring = 1;
  1104.    i = a;
  1105.    j = b;
  1106.    while(measuring){
  1107.       j--;
  1108.       i++;
  1109.       if(j >=0 && i<=ROWS-1){
  1110.          if(the_image[i][j] == value)
  1111.             dist8++;
  1112.          else
  1113.             measuring = 0;
  1114.       }
  1115.       else
  1116.          measuring = 0;
  1117.    }  /* ends while measuring */
  1118.    dist8 = (dist8*14)/10;
  1119.    if(dist8 <= result)
  1120.       result = dist8;
  1121.  
  1122.    return(result);
  1123. }  /* ends distance_8 */
  1124.  
  1125.  
  1126.  
  1127.  
  1128.  
  1129.      /*******************************************
  1130.      *
  1131.      *   mat(..
  1132.      *
  1133.      *   This function finds the medial axis
  1134.      *   transform for objects in an image.
  1135.      *   The mat are those points that are
  1136.      *   minimally distant to more than one
  1137.      *   boundary point.
  1138.      *
  1139.      *******************************************/
  1140.  
  1141.  
  1142. mat(in_name, out_name, the_image, out_image,
  1143.     il, ie, ll, le, value)
  1144.    char   in_name[], out_name[];
  1145.    int    il, ie, ll, le;
  1146.    short  the_image[ROWS][COLS],
  1147.           out_image[ROWS][COLS],
  1148.           value;
  1149. {
  1150.    int    a, b, count, i, j, k,
  1151.           length, width;
  1152.  
  1153.    create_file_if_needed(in_name, out_name, out_image);
  1154.  
  1155.    read_tiff_image(in_name, the_image, il, ie, ll, le);
  1156.  
  1157.    for(i=0; i<ROWS; i++)
  1158.       for(j=0; j<COLS; j++)
  1159.          out_image[i][j] = 0;
  1160.  
  1161.       /***************************
  1162.       *
  1163.       *   Loop over image array
  1164.       *
  1165.       ****************************/
  1166.  
  1167.    printf("\n");
  1168.  
  1169.    for(i=0; i<ROWS; i++){
  1170.       if( (i%10) == 0) printf("%3d", i);
  1171.       for(j=0; j<COLS; j++){
  1172.          if(the_image[i][j] == value)
  1173.             out_image[i][j] = mat_d(the_image, 
  1174.                                     i, j, value);
  1175.       }  /* ends loop over j */
  1176.    }  /* ends loop over i */
  1177.  
  1178.    write_array_into_tiff_image(out_name, out_image,
  1179.                                il, ie, ll, le);
  1180.  
  1181. }  /* ends mat */
  1182.  
  1183.  
  1184.  
  1185.      /*******************************************
  1186.      *
  1187.      *   mat_d(..
  1188.      *
  1189.      *   This function helps find the medial
  1190.      *   axis transform.
  1191.      *
  1192.      *   This function measures the distances
  1193.      *   from the point to a zero pixel in all
  1194.      *   eight directions.  Look for the two
  1195.      *   shortest distances in the eight distances.
  1196.      *   If the two shortest distances are
  1197.      *   equal, then the point in question
  1198.      *   is minimally distant to more than one
  1199.      *   boundary point.  Therefore, it is
  1200.      *   on the medial axis so return a value.
  1201.      *   Otherwise, return zero.
  1202.      *
  1203.      *******************************************/
  1204.  
  1205. mat_d(the_image, a, b, value)
  1206.    int   a, b;
  1207.    short the_image[ROWS][COLS], value;
  1208. {
  1209.    int i, j, measuring;
  1210.    short dist1  = 0,
  1211.          dist2  = 0,
  1212.          dist3  = 0,
  1213.          dist4  = 0,
  1214.          dist5  = 0,
  1215.          dist6  = 0,
  1216.          dist7  = 0,
  1217.          dist8  = 0,
  1218.          min1   = 255,
  1219.          min2   = 255,
  1220.          result = 0;
  1221.  
  1222.       /* straight up */
  1223.    measuring = 1;
  1224.    i = a;
  1225.    j = b;
  1226.    while(measuring){
  1227.       i--;
  1228.       if(i >= 0){
  1229.          if(the_image[i][j] == value)
  1230.             dist1++;
  1231.          else
  1232.             measuring = 0;
  1233.       }
  1234.       else
  1235.          measuring = 0;
  1236.    }  /* ends while measuring */
  1237.    result = dist1;
  1238.    min1   = dist1;
  1239.  
  1240.       /* straight down */
  1241.    measuring = 1;
  1242.    i = a;
  1243.    j = b;
  1244.    while(measuring){
  1245.       i++;
  1246.       if(i <= ROWS-1){
  1247.          if(the_image[i][j] == value)
  1248.             dist2++;
  1249.          else
  1250.             measuring = 0;
  1251.       }
  1252.       else
  1253.          measuring = 0;
  1254.    }  /* ends while measuring */
  1255.    if(dist2 <= result)
  1256.       result = dist2;
  1257.    if(dist2 < min1){
  1258.       min2 = min1;
  1259.       min1 = dist2;
  1260.    }
  1261.    else
  1262.       if(dist2 < min2)
  1263.          min2 = dist2;
  1264.  
  1265.       /* straight left */
  1266.    measuring = 1;
  1267.    i = a;
  1268.    j = b;
  1269.    while(measuring){
  1270.       j--;
  1271.       if(j >= 0){
  1272.          if(the_image[i][j] == value)
  1273.             dist3++;
  1274.          else
  1275.             measuring = 0;
  1276.       }
  1277.       else
  1278.          measuring = 0;
  1279.    }  /* ends while measuring */
  1280.    if(dist3 <= result)
  1281.       result = dist3;
  1282.    if(dist3 < min1){
  1283.       min2 = min1;
  1284.       min1 = dist3;
  1285.    }
  1286.    else
  1287.       if(dist3 < min2)
  1288.          min2 = dist3;
  1289.  
  1290.       /* straight right */
  1291.    measuring = 1;
  1292.    i = a;
  1293.    j = b;
  1294.    while(measuring){
  1295.       j++;
  1296.       if(j <= COLS-1){
  1297.          if(the_image[i][j] == value)
  1298.             dist4++;
  1299.          else
  1300.             measuring = 0;
  1301.       }
  1302.       else
  1303.          measuring = 0;
  1304.    }  /* ends while measuring */
  1305.    if(dist4 <= result)
  1306.       result = dist4;
  1307.    if(dist4 < min1){
  1308.       min2 = min1;
  1309.       min1 = dist4;
  1310.    }
  1311.    else
  1312.       if(dist4 < min2)
  1313.          min2 = dist4;
  1314.  
  1315.       /* left and up */
  1316.    measuring = 1;
  1317.    i = a;
  1318.    j = b;
  1319.    while(measuring){
  1320.       j--;
  1321.       i--;
  1322.       if(j >= 0 && i>=0){
  1323.          if(the_image[i][j] == value)
  1324.             dist5++;
  1325.          else
  1326.             measuring = 0;
  1327.       }
  1328.       else
  1329.          measuring = 0;
  1330.    }  /* ends while measuring */
  1331.    dist5 = ((dist5*14)+7)/10;
  1332.    if(dist5 <= result)
  1333.       result = dist5;
  1334.    if(dist5 < min1){
  1335.       min2 = min1;
  1336.       min1 = dist5;
  1337.    }
  1338.    else
  1339.       if(dist5 < min2)
  1340.          min2 = dist5;
  1341.  
  1342.       /* right and up */
  1343.    measuring = 1;
  1344.    i = a;
  1345.    j = b;
  1346.    while(measuring){
  1347.       j++;
  1348.       i--;
  1349.       if(j <=COLS-1 && i>=0){
  1350.          if(the_image[i][j] == value)
  1351.             dist6++;
  1352.          else
  1353.             measuring = 0;
  1354.       }
  1355.       else
  1356.          measuring = 0;
  1357.    }  /* ends while measuring */
  1358.    dist6 = ((dist6*14)+7)/10;
  1359.    if(dist6 <= result)
  1360.       result = dist6;
  1361.    if(dist6 < min1){
  1362.       min2 = min1;
  1363.       min1 = dist6;
  1364.    }
  1365.    else
  1366.       if(dist6 < min2)
  1367.          min2 = dist6;
  1368.  
  1369.       /* right and down */
  1370.    measuring = 1;
  1371.    i = a;
  1372.    j = b;
  1373.    while(measuring){
  1374.       j++;
  1375.       i++;
  1376.       if(j <=COLS-1 && i<=ROWS-1){
  1377.          if(the_image[i][j] == value)
  1378.             dist7++;
  1379.          else
  1380.             measuring = 0;
  1381.       }
  1382.       else
  1383.          measuring = 0;
  1384.    }  /* ends while measuring */
  1385.    dist7 = ((dist7*14)+7)/10;
  1386.    if(dist7 <= result)
  1387.       result = dist7;
  1388.    if(dist7 < min1){
  1389.       min2 = min1;
  1390.       min1 = dist7;
  1391.    }
  1392.    else
  1393.       if(dist7 < min2)
  1394.          min2 = dist7;
  1395.  
  1396.       /* left and down */
  1397.    measuring = 1;
  1398.    i = a;
  1399.    j = b;
  1400.    while(measuring){
  1401.       j--;
  1402.       i++;
  1403.       if(j >=0 && i<=ROWS-1){
  1404.          if(the_image[i][j] == value)
  1405.             dist8++;
  1406.          else
  1407.             measuring = 0;
  1408.       }
  1409.       else
  1410.          measuring = 0;
  1411.    }  /* ends while measuring */
  1412.    dist8 = ((dist8*14)+7)/10;
  1413.    if(dist8 <= result)
  1414.       result = dist8;
  1415.    if(dist8 < min1){
  1416.       min2 = min1;
  1417.       min1 = dist8;
  1418.    }
  1419.    else
  1420.       if(dist8 < min2)
  1421.          min2 = dist8;
  1422.  
  1423.    if(min1 == min2)
  1424.       result = value;
  1425.    else
  1426.       result = 0;
  1427.  
  1428.    if(min1 == 0)
  1429.       result = 0;
  1430.  
  1431.    return(result);
  1432. }  /* ends mat_d */
  1433.